package com.yupi.oj.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.oj.common.ErrorCode;
import com.yupi.oj.exception.BusinessException;
import com.yupi.oj.mapper.QuestionSubmitLogMapper;
import com.yupi.oj.model.dto.questionSubmitLog.QuestionSubmitLogAddRequest;
import com.yupi.oj.model.dto.questionSubmitLog.QuestionSubmitLogSearchRequest;
import com.yupi.oj.model.entity.Question;
import com.yupi.oj.model.entity.QuestionSubmitLog;
import com.yupi.oj.model.entity.User;
import com.yupi.oj.model.enums.SubmitStatusEnum;
import com.yupi.oj.model.vo.QuestionSubmitLogVO;
import com.yupi.oj.service.QuestionService;
import com.yupi.oj.service.QuestionSubmitLogService;
import com.yupi.oj.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author yanghaifeng
 * @description 针对表【QuestionSubmitLog_submit_log(做题提交记录表)】的数据库操作Service实现
 * @createDate 2024-04-11 15:36:58
 */
@Service
public class QuestionSubmitLogServiceImpl extends ServiceImpl<QuestionSubmitLogMapper, QuestionSubmitLog>
        implements QuestionSubmitLogService {


    @Autowired
    private UserService userService;

    @Autowired
    private QuestionService questionService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long add(QuestionSubmitLogAddRequest questionSubmitLogAddRequest, HttpServletRequest request) {
        Long questionId = questionSubmitLogAddRequest.getQuestionId();
        String submitLanguage = questionSubmitLogAddRequest.getSubmitLanguage();
        String codeDescription = questionSubmitLogAddRequest.getCodeDescription();

        // 请参校验
        if (StrUtil.hasBlank(submitLanguage, codeDescription)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (ObjectUtil.hasNull(questionId)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 逻辑校验
        // 检查题目是否存在
        Question question = questionService.getById(questionId);
        if (ObjectUtil.isNull(question)) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        // 数据持久化
        QuestionSubmitLog questionSubmitLog = new QuestionSubmitLog();

        BeanUtils.copyProperties(questionSubmitLogAddRequest, questionSubmitLog);
        // TODO: 2024/4/12 执行内存和执行时间需要等代码沙箱执行后才知道
        questionSubmitLog.setMemoryConsume(0);
        questionSubmitLog.setExecuteTime(0);

        double codeBytesSize = textByteSizeCalculator(codeDescription);
        questionSubmitLog.setCodeLength(codeBytesSize);
        questionSubmitLog.setSubmitStatus(SubmitStatusEnum.COMPILE.getValue());
        User loginUser = userService.getLoginUser(request);
        questionSubmitLog.setCreateBy(loginUser.getUserAccount());
        questionSubmitLog.setUpdateBy(loginUser.getUserAccount());
        this.save(questionSubmitLog);
        return questionSubmitLog.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean delete(Long id, HttpServletRequest request) {
        // 请参校验
        if (ObjectUtil.isNull(id)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 逻辑校验
        QuestionSubmitLog questionSubmitLog = this.getById(id);
        if (ObjectUtil.isNull(questionSubmitLog)) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        return this.removeById(id);
    }


    @Override
    public QuestionSubmitLogVO queryById(Long id) {
        // 请参校验
        if (ObjectUtil.isNull(id)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        QuestionSubmitLog questionSubmitLog = this.getById(id);
        if (ObjectUtil.isNull(questionSubmitLog)) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "问题不存在");
        }
        return QuestionSubmitLogVO.beanToVO(questionSubmitLog);
    }


    @Override
    public List<QuestionSubmitLogVO> queryList(QuestionSubmitLogSearchRequest questionSubmitLogSearchRequest) {
        String submitLanguage = questionSubmitLogSearchRequest.getSubmitLanguage();
        Integer submitStatus = questionSubmitLogSearchRequest.getSubmitStatus();
        String errorInfo = questionSubmitLogSearchRequest.getErrorInfo();
        String createBy = questionSubmitLogSearchRequest.getCreateBy();

        List<QuestionSubmitLogVO> result = new ArrayList<>();
        // 分页查询
        List<QuestionSubmitLog> list = this.list(Wrappers.lambdaQuery(QuestionSubmitLog.class)
                .eq(StrUtil.isNotBlank(submitLanguage), QuestionSubmitLog::getSubmitLanguage, submitLanguage)
                .eq(ObjectUtil.isNotNull(submitStatus), QuestionSubmitLog::getSubmitStatus, submitStatus)
                .like(StrUtil.isNotEmpty(errorInfo), QuestionSubmitLog::getErrorInfo, errorInfo)
                .eq(StrUtil.isNotBlank(createBy), QuestionSubmitLog::getCreateBy, createBy));

        // 数据转换
        if (ObjectUtil.isNotEmpty(list)) {
            result = list.stream().map(QuestionSubmitLogVO::beanToVO).collect(Collectors.toList());
        }
        return result;
    }

    @Override
    public List<QuestionSubmitLogVO> queryListByQuestionId(Long questionId) {
        if (ObjectUtil.isNull(questionId)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        List<QuestionSubmitLogVO> result = new ArrayList<>();
        List<QuestionSubmitLog> list = this.list(Wrappers.lambdaQuery(QuestionSubmitLog.class)
                .eq(QuestionSubmitLog::getQuestionId, questionId)
                .orderByDesc(QuestionSubmitLog::getCreateTime));
        if (ObjectUtil.isEmpty(list)) {
            return result;
        }
        result = list.stream().map(QuestionSubmitLogVO::beanToVO).collect(Collectors.toList());
        return result;
    }


    /**
     * 获取文本的字节大小
     *
     * @param text 文本
     * @return 字节大小（KB）
     */
    public static double textByteSizeCalculator(String text) {
        byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
        return bytes.length;
    }
}




